/**
 * Software License, Version 1.0 Copyright 2003 The Trustees of Indiana
 * University. All rights reserved. Redistribution and use in source and binary
 * forms, with or without modification, are permitted provided that the
 * following conditions are met: 1) All redistributions of source code must
 * retain the above copyright notice, the list of authors in the original source
 * code, this list of conditions and the disclaimer listed in this license; 2)
 * All redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer listed in this license in the
 * documentation and/or other materials provided with the distribution; 3) Any
 * documentation included with all redistributions must include the following
 * acknowledgement: "This product includes software developed by the Community
 * Grids Lab. For further information contact the Community Grids Lab at
 * http://communitygrids.iu.edu/." Alternatively, this acknowledgement may
 * appear in the software itself, and wherever such third-party acknowledgments
 * normally appear. 4) The name Indiana University or Community Grids Lab or
 * NaradaBrokering, shall not be used to endorse or promote products derived
 * from this software without prior written permission from Indiana University.
 * For written permission, please contact the Advanced Research and Technology
 * Institute ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202. 5)
 * Products derived from this software may not be called NaradaBrokering, nor
 * may Indiana University or Community Grids Lab or NaradaBrokering appear in
 * their name, without prior written permission of ARTI. Indiana University
 * provides no reassurances that the source code provided does not infringe the
 * patent or any other intellectual property rights of any other entity. Indiana
 * University disclaims any liability to any recipient for claims brought by any
 * other entity based on infringement of intellectual property rights or
 * otherwise. LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH
 * NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY
 * GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF
 * INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS.
 * INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS",
 * "VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.
 * LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR
 * ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION
 * GENERATED USING SOFTWARE.
 */
package cgl.narada.test.security;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Properties;
import java.util.Random;

import org.apache.log4j.Logger;

import cgl.narada.discovery.topics.TopicDiscoveryClient;
import cgl.narada.discovery.topics.Topics;
import cgl.narada.discovery.topics.messages.SignedTopicAdvertisement;
import cgl.narada.event.NBEvent;
import cgl.narada.event.TemplateProfileAndSynopsisTypes;
import cgl.narada.matching.Profile;
import cgl.narada.service.ServiceException;
import cgl.narada.service.client.ClientService;
import cgl.narada.service.client.EventConsumer;
import cgl.narada.service.client.NBEventListener;
import cgl.narada.service.client.SessionService;
import cgl.narada.service.qos.ConsumerConstraints;
import cgl.narada.service.security.kmc.KMCClient;
import cgl.narada.service.security.kmc.TopicRights;
import cgl.narada.service.security.kmc.messages.SecureTopicKeyResponse;
import cgl.narada.service.security.securityprovider.CertificateManager;
import cgl.narada.service.security.securityprovider.CertificateUtil;
import cgl.narada.util.SystemInit;
import cgl.narada.util.SystemNotInitializedException;

public class SecureDataReciever implements NBEventListener {

	static Logger log = Logger.getLogger("SecureDataReciever");

	public static void main(String[] args) {
		SystemInit.init();
		if (args.length > 1) host = args[1];
		if (args.length > 2) port = args[2];
		if (args.length > 3) prot = args[3];

		SecureDataReciever reciever = new SecureDataReciever(args);
	}

	public SecureDataReciever(String[] a) {
		x = 0;

		String keystore = null;
		try {
			configFileLocation = SystemInit
					.getInitData(SystemInit.SYS_SERVICE_CONFIG_PATH);
			keystore = SystemInit.getInitData(SystemInit.SYS_KEYSTORE);
		}
		catch (SystemNotInitializedException e) {
			e.printStackTrace();
		}

		initTopics(keystore);
		if (a.length > 0) {
			if (a[0].equals("0"))
				init(false);
			else
				init(true);
		}
	}

	private static String host = "localhost";
	private static String port = "25000";
	private static String prot = "niotcp";
	private String configFileLocation;;
	private String topicName = "encrypted";

	private String topicUUID;

	private EventConsumer consumer;
	private SecureTopicKeyResponse r2;
	private int x;

	public void onEvent(NBEvent nbEvent) {
		byte[] data = nbEvent.getContentPayload();
		++x;
		System.out.println("GOT: <" + x + ">: " + (new String(data)));
	}

	private void init(boolean zz) {

		// IMP: Might conflict w/ other ppl's entity IDs Maintain constant for
		// now
		int entityId = (new Random()).nextInt();

		Properties prop = new Properties();

		prop.put("hostname", host);
		prop.put("portnum", port);

		log.info("SecureTopicsManager:- TCP @ " + host + ":" + port
				+ " EntityID[" + entityId + "]");

		try {
			ClientService clientService = SessionService.getClientService(
					entityId, configFileLocation);

			System.out.println("Subscribing to : " + topicUUID);

			clientService.initializeBrokerCommunications(prop, prot);
			Profile profile = clientService.createProfile(
					TemplateProfileAndSynopsisTypes.STRING, topicUUID);

			consumer = clientService.createEventConsumer(this);

			ConsumerConstraints cc = consumer
					.createConsumerConstraints(profile);
			cc.setReceiveSecurely(entityId);
			cc.setSecurityToken(r2.getSignedSecurityToken(), r2.getKey(), null,
					zz, rootCA);

			consumer.subscribeTo(profile, cc);

		}
		catch (ServiceException e) {
			log.error("", e);
		}
	}

    PublicKey rootCA;
    
	public void initTopics(String keystore) {
		CertificateManager certMan = new CertificateManager();
		certMan.init(keystore, null);

		rootCA = CertificateUtil.getPublicKey(certMan,
				certMan.ROOT_CA_ALIAS);

		Certificate c2_cert = CertificateUtil.getCertificate(certMan, "c2");
		PrivateKey c2_priv = CertificateUtil.getPrivateKey(certMan, "c2");

		// First discover the topic...
		SignedTopicAdvertisement[] stas = discoverTopics(c2_cert, c2_priv,
				topicName, Topics.MATCHING_STRING, 2);

		KMCClient client2 = new KMCClient(c2_cert, c2_priv, rootCA, "/kmc/c2",
				configFileLocation, host, port, prot);

		TopicRights reqRights = new TopicRights(TopicRights.SUBSCRIBE_RIGHT);

		// Now try to get the security token...

		r2 = client2.requestTopicKey(stas[0].getTopicAd().getTopicSynopsis(),
				c2_cert, reqRights, 5000);

		if (r2 == null)
			System.out.println("Request Denied / Timeout occurred !");
		else {
			System.out.println("Sec Token:"
					+ r2.getSignedSecurityToken().getSecurityToken()
							.getValidity().toString());
			topicUUID = stas[0].getTopicAd().getTopicSynopsis();

		}

	}

	public SignedTopicAdvertisement[] discoverTopics(Certificate cert,
			PrivateKey priv, String synopsis, int matchType, int maxTopics) {

		TopicDiscoveryClient disco = new TopicDiscoveryClient(15000,
				configFileLocation, cert, priv, host, port, prot);

		SignedTopicAdvertisement[] stas = disco.discover(matchType, synopsis,
				null, maxTopics);

		disco.close();

		return stas;
	}
}
